#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include "ReceivePartAn.h"
/************************COMMON************************/
//自定义标识符，最终是以16进制来显示
// 共享内存访问标识
#define MM_KEY 0x12
// 信号量访问标识
#define SEM_KEY 0x34
// 共享内存指针
char *shm_start = NULL;
int semid;
int shm_id;

union semun
{
    int val;
    /* Value for SETVAL */
    struct semid_ds *buf;
    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short *array; /* Array for GETALL, SETALL */
    struct seminfo *__buf; /* Buffer for IPC_INFO
                 (Linux-specific) */
};

unsigned int *BboxNum;
Bbox * box;

//初始化信号量
int init_sem(int sem_id, int init_value)
{
    union semun sem_union;
    sem_union.val = init_value;
    if (semctl(sem_id, 0, SETVAL, sem_union) == -1)
    {
        printf("Initialize semaphore.\n");
        return -1;
    }
    return 0;
}

int sem_p(int semid)
{
    struct sembuf mybuf; // 对信号量做减1操作，即等待P（sv）
    mybuf.sem_num = 0;
    mybuf.sem_op = -1;
    mybuf.sem_flg = SEM_UNDO;
    if (semop(semid, &mybuf, 1) < 0)

    {
        perror("semop");
        exit(1);
    }

    return 0;
}
int sem_v(int semid)
{
    struct sembuf mybuf;
    mybuf.sem_num = 0;
    mybuf.sem_op = 1;
    mybuf.sem_flg = SEM_UNDO;
    if (semop(semid, &mybuf, 1) < 0)

    {
        perror("semop");
        exit(1);
    }

    return 0;
}
int del_sem(int sem_id)
{
    union semun sem_union;
    if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
    {
        perror("Delete semahore.\n");
        return -1;
    }
}

Bbox myBox;
bool boxIsRead;

void* getShareMem(void*)
{
    int ret;
    // 1.创建共享内存
    shm_id = shmget(MM_KEY, 4096, IPC_CREAT | 0664);
    if (shm_id < 0)
    {
        perror("shmget error");
        return NULL;
    }

    // 2.建立映射关系
    shm_start = (char*)shmat(shm_id, NULL, 0);
    if (shm_start == (char *)-1)
    {
        perror("shmat error");
        return NULL;
    }
    // 3.创建信号量
    semid = semget(SEM_KEY, 1, IPC_CREAT | 0666); //创建一个信号量
    BboxNum = (unsigned int *)shm_start;
    box = (Bbox *)(shm_start + 4);

    //****************************************************************************/
    // 3.进行内存操作

    {
        sem_p(semid); //获取信号量
        if(*BboxNum)
        {
            myBox=*box;
            boxIsRead=true;
        }
        *BboxNum=0;
        // printf("data = %d\r\n", *BboxNum);
        sem_v(semid); //获取信号量
        
        sleep(1);
    }
    ret = shmdt(shm_start);
    // ret = del_sem(semid);
}

bool getBoxValue(Bbox& tmp)
{
    if(!boxIsRead) return false;
    tmp=myBox;
    return true;
}

